a11y: Do not notify of empty state changes
authorEmmanuele Bassi <ebassi@gnome.org>
Wed, 5 Aug 2020 17:05:46 +0000 (18:05 +0100)
committerEmmanuele Bassi <ebassi@gnome.org>
Tue, 25 Aug 2020 15:36:08 +0000 (16:36 +0100)
If the ATContext state hasn't changed—for instance, if the accessible
attributes have been set to their default value, or have been set to the
same value—do not emit an accessible state change. State changes can be
arbitrarily expensive, so we want to ensure that they are meaningful.

gtk/gtkatcontext.c
gtk/gtkatcontextprivate.h

index 9cdbd0e9f3d70e1391eb730e990fd1cb23bc49a5..e1e2edd59914ab2b9ace767ea24b6734cff7363c 100644 (file)
@@ -425,6 +425,12 @@ gtk_at_context_update (GtkATContext *self)
 {
   g_return_if_fail (GTK_IS_AT_CONTEXT (self));
 
+  /* There's no point in notifying of state changes if there weren't any */
+  if (self->updated_properties == 0 &&
+      self->updated_relations == 0 &&
+      self->updated_states == 0)
+    return;
+
   GtkAccessibleStateChange changed_states =
     gtk_accessible_attribute_set_get_changed (self->states);
   GtkAccessiblePropertyChange changed_properties =
@@ -435,6 +441,10 @@ gtk_at_context_update (GtkATContext *self)
   g_signal_emit (self, obj_signals[STATE_CHANGE], 0,
                  changed_states, changed_properties, changed_relations,
                  self->states, self->properties, self->relations);
+
+  self->updated_properties = 0;
+  self->updated_relations = 0;
+  self->updated_states = 0;
 }
 
 /*< private >
@@ -457,10 +467,15 @@ gtk_at_context_set_accessible_state (GtkATContext       *self,
 {
   g_return_if_fail (GTK_IS_AT_CONTEXT (self));
 
+  gboolean res = FALSE;
+
   if (value != NULL)
-    gtk_accessible_attribute_set_add (self->states, state, value);
+    res = gtk_accessible_attribute_set_add (self->states, state, value);
   else
-    gtk_accessible_attribute_set_remove (self->states, state);
+    res = gtk_accessible_attribute_set_remove (self->states, state);
+
+  if (res)
+    self->updated_states |= (1 << state);
 }
 
 /*< private >
@@ -519,10 +534,15 @@ gtk_at_context_set_accessible_property (GtkATContext          *self,
 {
   g_return_if_fail (GTK_IS_AT_CONTEXT (self));
 
+  gboolean res = FALSE;
+
   if (value != NULL)
-    gtk_accessible_attribute_set_add (self->properties, property, value);
+    res = gtk_accessible_attribute_set_add (self->properties, property, value);
   else
-    gtk_accessible_attribute_set_remove (self->properties, property);
+    res = gtk_accessible_attribute_set_remove (self->properties, property);
+
+  if (res)
+    self->updated_properties |= (1 << property);
 }
 
 /*< private >
@@ -581,10 +601,15 @@ gtk_at_context_set_accessible_relation (GtkATContext          *self,
 {
   g_return_if_fail (GTK_IS_AT_CONTEXT (self));
 
+  gboolean res = FALSE;
+
   if (value != NULL)
-    gtk_accessible_attribute_set_add (self->relations, relation, value);
+    res = gtk_accessible_attribute_set_add (self->relations, relation, value);
   else
-    gtk_accessible_attribute_set_remove (self->relations, relation);
+    res = gtk_accessible_attribute_set_remove (self->relations, relation);
+
+  if (res)
+    self->updated_relations |= (1 << relation);
 }
 
 /*< private >
index 2ac85bde2d47025eb04f3e1237ece4080bd066a9..2b916187fdc8a1614370df52c24ef7ffbb685478 100644 (file)
@@ -90,6 +90,10 @@ struct _GtkATContext
   GtkAccessibleAttributeSet *states;
   GtkAccessibleAttributeSet *properties;
   GtkAccessibleAttributeSet *relations;
+
+  GtkAccessibleStateChange updated_states;
+  GtkAccessiblePropertyChange updated_properties;
+  GtkAccessibleRelationChange updated_relations;
 };
 
 struct _GtkATContextClass